#!/usr/bin/env python

'''cloud api for paas'''
import os
import sys
import subprocess
import pp
import re

'''environment variable'''
ONE_LOCATION=os.getenv('ONE_LOCATION')
USER=os.getenv('USER')
HOME_DIR=os.getenv('HOME')

'''one command'''
if ONE_LOCATION:
    CREATE_CMD=ONE_LOCATION+r"/bin/vmcreate"
    CR_CMD=ONE_LOCATION+r"/bin/vmcr"
    DEL_CMD=ONE_LOCATION+r"/bin/vmdel"
    SHOW_CMD=ONE_LOCATION+r"/bin/vmshow"
else:
    CREATE_CMD="/usr/bin/vmcreate"
    CR_CMD="/usr/bin/vmcr"
    DEL_CMD="/usr/bin/vmdel"
    SHOW_CMD="/usr/bin/vmshow"

'''variable'''
CONF_DIR="/tmp/cloud"
SRC_FILE="/srv/cloud/images/base.one"

'''initialize the configure file of vms'''
def init_conf(f_conf):
    if "name" not in f_conf:
        f_conf["name"]=USER
    if "vcpu" not in f_conf:
        f_conf["vcpu"]=1
    if "cpu" not in f_conf:
        f_conf["cpu"]=f_conf["vcpu"]
    if "HOME" not in f_conf:
        f_conf["HOME"]=HOME_DIR
    if "count" not in f_conf:
        f_conf["count"]=1

'''get the img file type
ret 0 para-vm
    1 full-vm'''
def get_vm_type(img_file):
    f=subprocess.Popen(("/usr/bin/file",img_file),stdout=subprocess.PIPE).stdout
    FILE_TYPE=f.readline()
    f.close()
    TYPE=re.search("ext3",FILE_TYPE)
    if TYPE is not None:
        return 0
    else:
        return 1

'''create a vm'''
def vm_sub(CON_F):
    CREATE_CMD="/srv/crane/one/bin/vmcreate"
    f=subprocess.Popen((CREATE_CMD, CON_F), stdout=subprocess.PIPE).stdout
    vm_id=f.readline().strip()
    f.close
    is_id=re.search('[0-9]*',vm_id)
    if is_id is not None:
        return vm_id
    else:
        return -1

'''create vms in ruby'''
def vm_cr(CON_F,num):
    vms_id=[]
    f=subprocess.Popen((CR_CMD, CON_F, str(num)), stdout=subprocess.PIPE).stdout
    for each in f:
        is_id=re.search('[0-9]*',each.strip())
        if is_id is not None:
            vms_id.append(each.strip())
    f.close
    return vms_id

'''create vms one by one'''
def vms_submit(CON_F,num):
    ids = []
    index = 0
    while index < num:
        id=vm_sub(CON_F)
        if id is not -1:
            index += 1
            ids.append(id)   
    return ids

'''create vms in parallel with the file'''
def p_vms_submit(CON_F,num):
    ppservers=()
    job_server=pp.Server(num, ppservers=ppservers)
    ids = []
    jobs = []
    index = 0
    while index < num:
        jobs.append(job_server.submit(vm_sub, (CON_F,), (),("re","subprocess",)))
        index += 1
    for job in jobs:
        id=job()
        if id is not -1:
            ids.append(id)   
    return ids

'''get a ip from a id'''
def get_ip(id):
    SHOW_CMD="/srv/crane/one/bin/vmshow"
    f=subprocess.Popen((SHOW_CMD, "show", str(id)), stdout=subprocess.PIPE).stdout
    show_list=f.read().strip()
    f.close
    is_ip=re.search('IP=([\.0-9]*)',show_list)
    if is_ip is not None:
        return [id,is_ip.group(1)]
    else:
        return -1

'''get ips from ids one by one'''
def get_ip_list(id_list):
    ip_list = []
    index = 0
    while index < len(id_list):
        ip=get_ip(id_list[index])
        if ip is not -1:
            index += 1
            ip_list.append(ip)
    return ip_list

'''parallel get ips from ids'''
def p_get_ip_list(id_list):
    ppservers=()
    job_server=pp.Server(len(id_list), ppservers=ppservers)
    ip_list = []
    jobs = []
    index = 0
    while index < len(id_list):
        jobs.append(job_server.submit(get_ip, (id_list[index],), (),("re","subprocess",)))
        index += 1
    for job in jobs:
        ip=job()
        ip_list.append(ip)
    return ip_list

'''creat vms with a configure file'''
def create_vm(HVM):
    init_conf(HVM)
    f=os.popen('date +%s')
    DATE=f.readline().strip()
    f.close()
    CONF_FILE=CONF_DIR+os.sep+USER+"_"+DATE+".one"
    subprocess.call(("/bin/cp",SRC_FILE,CONF_FILE))
    fp=open(CONF_FILE,"a")
    for each in ["name","cpu","memory","vcpu","HOME"]:
        fp.write(each+"="+str(HVM[each])+os.linesep)
    if get_vm_type(HVM["img"]):
        '''full-vm'''
        fp.write(r'''GRAPHICS=[type ="vnc",listen="0.0.0.0"]'''+os.linesep)
        fp.write(r'''RAW =[type="xen",data="builder='hvm'"]'''+os.linesep)
        fp.write(r'''RAW =[type="xen",data="device_model='/usr/lib64/xen/bin/qemu-dm'"]'''+os.linesep)
        fp.write(r'''OS  =[kernel="/usr/lib/xen/boot/hvmloader" ]'''+os.linesep)
        fp.write(r'''DISK=[source="'''+HVM["img"]+r'''", target = "hda", clone = "yes" ]'''+os.linesep)
    else:
        '''para-vm'''
        pass
    fp.close()
    id_list=p_vms_submit(CONF_FILE, int(HVM["count"]))
    #id_list=vm_cr(CONF_FILE, int(HVM["count"]))
    subprocess.call(("/bin/rm","-f",CONF_FILE))
    return p_get_ip_list(id_list)
    
'''delete a vm with the id'''
def del_vm(vm_id):
    f=subprocess.Popen((DEL_CMD, str(vm_id)), stdout=subprocess.PIPE).stdout
    ret=f.readline().strip()
    f.close()
    if re.search('correct',ret) is not None:
        return 0 

'''delete a vm of the user with the id'''
def del_vm(vm_id,user):
    f=subprocess.Popen((DEL_CMD, str(vm_id)), stdout=subprocess.PIPE).stdout
    ret=f.readline().strip()
    f.close()
    if re.search('correct',ret) is not None:
        return 0 

'''delete a group of vms from vm_id_start to vm_id_end'''
def del_vms(vm_id_start,vm_id_end):
    ids_del=[ str(each) for each in range(int(vm_id_start),int(vm_id_end)+1) ]
    f=subprocess.Popen([DEL_CMD]+ids_del, stdout=subprocess.PIPE).stdout
    f.close()

'''test'''
if __name__ == "__main__":
    #HVM={ 'memory':'512','vcpu':'2','img':'/srv/cloud/images/rhel5_x86_64_base.img','count':20 }
    #date1=subprocess.call(("/bin/date","+%T"))
    #ret=create_vm(HVM)
    #date1=subprocess.call(("/bin/date","+%T"))
    #print ret
    HVM={ 'memory':'512','vcpu':'2','img':'/srv/cloud/images/rhel5_x86_64_base.img','count':1 }
    date1=subprocess.call(("/bin/date","+%T"))
    ret=create_vm(HVM)
    date1=subprocess.call(("/bin/date","+%T"))
    print ret
    #del_vms(573,587)
